#include <stdio.h>
#include <string.h>

#include "ak_common.h"
#include "ak_log.h"
#include "ak_vi.h"
#include "VideoCapture.h"


/******************Video Define********************/
#define VIDEO_CHANNEL_NUM   VIDEO_CHN0
#define VIDEO_DEV_ID    0
#define DMA_ENABLE  0
#define VIDEO_HEIGHT    480
#define VIDEO_WIDTH     640

// #define DMA_ENABLE  1    TODO 
#define DEF_FRAME_DEPTH     3
#define ISP_PATH "isp_pr2000_dvp_pal_25fps_27M.conf"

int VideoCaptureInit(void)
{
    /*
     * step 0: global value initialize
     */
    int ret = -1;                                //return value
    int width = VIDEO_WIDTH;
    int height = VIDEO_HEIGHT;
    int chn_main_id = VIDEO_CHN0;
    VI_CHN_ATTR chn_attr = {0};

    /* open vi flow */

    /*
     * step 1: open video input device
     */
    ret = ak_vi_open(VIDEO_DEV_ID);
    if (AK_SUCCESS != ret) {
        ak_print_error_ex(MODULE_ID_APP, "vi device %d open failed\n", VIDEO_DEV_ID);
        return ret;
    }

    /* default vi ae para */
#ifdef AK_RTOS
#ifndef __CHIP_AK37E_SERIES
#include "ak_vpss.h"
    struct vpss_isp_ae_init_info ae_init_info;
    ae_init_info.a_gain = 256;
    ae_init_info.d_gain = 256;
    ae_init_info.exp_time = 2154;
    ae_init_info.isp_d_gain = 256;
    ak_vpss_set_ae_init_info(VIDEO_DEV_ID, &ae_init_info);
#endif
#endif

    /*
     * step 3: get sensor support max resolution
     */
    RECTANGLE_S res;                //max sensor resolution
    VI_DEV_ATTR    dev_attr;
    memset(&dev_attr, 0, sizeof(VI_DEV_ATTR));
    dev_attr.dev_id = VIDEO_DEV_ID;
    dev_attr.crop.left = 0;
    dev_attr.crop.top = 0;
    dev_attr.crop.width = width;
    dev_attr.crop.height = height;
    dev_attr.max_width = width;
    dev_attr.max_height = height;
    dev_attr.sub_max_width = width;
    dev_attr.sub_max_height = height;

    /* get sensor resolution */
    ret = ak_vi_get_sensor_resolution(VIDEO_DEV_ID, &res);
    if (ret) {
        ak_print_error_ex(MODULE_ID_APP, "Can't get dev[%d]resolution\n", VIDEO_DEV_ID);
        ak_vi_close(VIDEO_DEV_ID);
        return ret;
    } else {
        ak_print_normal_ex(MODULE_ID_APP, "get dev res w:[%d]h:[%d]\n",res.width, res.height);
        dev_attr.crop.width = res.width;
        dev_attr.crop.height = res.height;
    }

    /*
     * step 4: set vi device working parameters
     * default parameters: 25fps, day mode
     */
    ret = ak_vi_set_dev_attr(VIDEO_DEV_ID, &dev_attr);
    if (ret) {
        ak_print_error_ex(MODULE_ID_APP, "vi device %d set device attribute failed!\n", VIDEO_DEV_ID);
        ak_vi_close(VIDEO_DEV_ID);
        return ret;
    }

    /*
     * step 5: set main channel attribute
     */

    memset(&chn_attr, 0, sizeof(VI_CHN_ATTR));
    chn_attr.chn_id = chn_main_id;
    chn_attr.res.width = width;
    chn_attr.res.height = height;
    chn_attr.frame_depth = DEF_FRAME_DEPTH;
    /*disable frame control*/
    chn_attr.frame_rate = 0;
    ret = ak_vi_set_chn_attr(chn_main_id, &chn_attr);
    if (ret) {
        ak_print_error_ex(MODULE_ID_APP, "vi device %d set channel [%d] attribute failed!\n", VIDEO_DEV_ID, chn_main_id);
        ak_vi_close(VIDEO_DEV_ID);
        return ret;
    }
    ak_print_normal_ex(MODULE_ID_APP, "vi device %d main sub channel attribute\n", VIDEO_DEV_ID);

	/*
     * step 8: enable vi device
     */
    ret = ak_vi_enable_dev(VIDEO_DEV_ID);
    if (ret) {
        ak_print_error_ex(MODULE_ID_APP, "vi device %d enable device  failed!\n", VIDEO_DEV_ID);
        ak_vi_close(VIDEO_DEV_ID);
        return ret;
    }

    /*
     * step 9: enable vi main channel
     */
    ret = ak_vi_enable_chn(chn_main_id);
    if(ret)
    {
        ak_print_error_ex(MODULE_ID_APP, "vi channel[%d] enable failed!\n", chn_main_id);
        ak_vi_close(VIDEO_DEV_ID);
        return ret;
    }
    return 0;
}

int TryCapture(void)
{
    int count = 0;
    int chn_id = 0;
    struct video_input_frame frame = {0};
    int ret = -1;

    ret = ak_vi_get_frame(chn_id, &frame);
    if(!ret)
    {
        FILE *fd;
        /*
        * open appointed file to save YUV data
        * save main channel yuv here
        */
        fd = fopen(VIDEO_FILE_PATH, "w+b");
        if (fd) 
        {
            unsigned char *buf = frame.vi_frame.data;
            unsigned int   len = frame.vi_frame.len;
            ret = fwrite(buf, 1, len, fd);
            if(ret < len)
            {
                ak_print_error(MODULE_ID_APP, "write yuv file failed!!\n");
                fclose(fd);
                return -1;
            }

            fclose(fd);
        } 
        else 
        {
            ak_print_normal(MODULE_ID_APP, "open YUV file[%s] failed!!\n", VIDEO_FILE_PATH);
        }
        /*
            * in this context, this frame was useless,
            * release frame data
            */
        ak_vi_release_frame(chn_id, &frame);
        count++;
    }
    else 
    {
        ak_print_normal_ex(MODULE_ID_APP, "get frame failed!\n");
        return -1;
    }

    return 0;
}

int VideoCaptureDeinit(void)
{
    ak_vi_disable_chn(VIDEO_CHANNEL_NUM);
	ak_vi_disable_dev(VIDEO_DEV_ID);
    ak_vi_close(VIDEO_DEV_ID);
}